# -*- coding: utf-8 -*-
'''
Copyright 2012 Rich Hill

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
'''



import os
import time
import sys
import win32serviceutil
import win32service
import win32event
import servicemanager
import pickle
import traceback

def we_are_frozen():
	"""Returns whether we are frozen via py2exe.
	This will affect how we find out where we are located."""
	return hasattr(sys, "frozen")


def module_path():
	""" This will get us the program's directory,
	even if we are frozen using py2exe"""

	if we_are_frozen():
		return os.path.dirname(unicode(sys.executable, sys.getfilesystemencoding( )))

	return os.path.dirname(unicode(__file__, sys.getfilesystemencoding( )))

cwd=module_path()
if cwd=='':
	cwd=os.getcwd()
	
sys.path.append('%s\\modules\\' % cwd)

import VariableParser
import ReadDatabase
import TweetForecast
import GetSunTimes

variablesfile='%s\\data\\tfa-nexus-weather-tweeter.ini' % cwd
twittervaluesfile='%s\\data\\TwitterAuth.ini' % cwd
tmpdatafile='%s\\tmp\data' % cwd
logfile='%s\\tmp\\log.txt' % cwd
showdebugmessages=False

def debug(message):
	if showdebugmessages:
		#outputfile.write('%s,%s\n' % (time.time(), message) )
		try:
			log=open(logfile,'a+')
			log.write('%s,%s \r\n' %  (time.ctime(),str(message) ))
		except:
			try:
				log=open(logfile,'a+')
				log.write('%s, unable to write message to log' % time.ctime() )
			except:
				pass
		log.flush()
		log.close()
		
def formatExceptionInfo(maxTBlevel=5):
		cla, exc, trbk = sys.exc_info()
		excName = cla.__name__
		try:
			excArgs = exc.__dict__["args"]
		except KeyError:
			excArgs = "<no args>"
		excTb = traceback.format_tb(trbk, maxTBlevel)
		return (excName, excArgs, excTb)		

class AppServerSvc (win32serviceutil.ServiceFramework):
	_svc_name_="TFA_Nexus_WeatherStation_Tweeter"
	_svc_display_name_="TFA Nexus WeatherStation Tweeter"
	_svc_description_="Sends tweets from the TFA Nexus weatherstation by interogating it's database on a regular interval"
	
	def __init__(self,args):
		win32serviceutil.ServiceFramework.__init__(self,args)
		self.hWaitStop = win32event.CreateEvent(None,0,0,None)
		
	def SvcStop(self):
		self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
		win32event.SetEvent(self.hWaitStop)	
		
	def SvcDoRun(self):
		servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
									servicemanager.PYS_SERVICE_STARTED,
									(self._svc_name_,''))
		self.timeout = 3000     
		self.variables=GetVariables(variablesfile)
		self.nexttime=time.time()+int(self.variables['LoopTime'])
		self.loopcount=0
		debug('%s' % str(self.variables) )
		while 1:
			rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout)
			#rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout)
         
			if rc == win32event.WAIT_OBJECT_0:
				servicemanager.LogInfoMsg("TFA_Nexus_WeatherStation_Tweeter - STOPPED!") 
				break
			else:
				try:
					debug('Launching main loop')
					
					self.loopcount=self.loopcount+1
					debug('%s:%s' % (str( time.time() ),str(self.nexttime) ) )
					if self.loopcount==1 or time.time() >= self.nexttime:
						debug('Conditions have been met to run main code section')
						self.nexttime=self.nexttime+int(self.variables['LoopTime'])
						returncode=main(self.variables)
						debug('Mainloop returncode:%d' % returncode)
						time.sleep(1)
						
					'''
					for i in range(0,int( self.variables['LoopTime'] ) ):
						else:
							time.sleep(1)
					'''
				except:
					debug( str( formatExceptionInfo() ) )
					pass

def GetVariables(filename):
	variables=VariableParser.Read(filename)
	debug('Reading variables file:%s' % filename)
	if variables[0] != 0:
		debug( "There was a problem with the ini file: %s" % filename)
		if variables[0]==1: problem="File not found"
		if variables[0]==2: problem="Unknown error. Please check the file for errors"
		debug( "The problem was: %s" % problem)
		sys.exit(1)
	else:
		variables=variables[1]
		debug('Variables loaded OK')
		
	return variables

def main(variables):
	# Get the twitter variables
	debug('reading twitter keys and tokens')
	twittervariables=GetVariables(twittervaluesfile)	
	
	# Load the tmpdata file to see how many records were in the database on the last run. If the value is the same then we don't need to run again
	#	if the file doesn't exist we'll assume that this is the first time that we've been executed
	
	debug('loading %s' % tmpdatafile)
	
	if os.path.exists(tmpdatafile):
		try:
			tempdata=pickle.load( open( tmpdatafile, "rb" ) )
		except:
			tempdata={'dblen':0}
	else:
		tempdata={'dblen':0}
	debug('Tempdata:')
	debug(str(tempdata) )
	debug('Checking Database file location is in variables file..')
	
	if not 'DatabaseFile' in variables:
		debug( "DatabaseFile value missing from variables file: %s\nPlease fix this error and retry" % variablesfile)
		sys.exit(2)

	# Check to see if the forecast has changed
	unscheduledtweet=False
	scheduledtweet=False
	
	DB=ReadDatabase.GetForecast(variables)

	tempdata['dblen']=DB.dbsize
	if DB.currentforecast != DB.penultimateforecast: unscheduledtweet=True
	
	# Check to see if a scheduled tweet is required
	count=0
	for hour in variables['Schedule']:
		if int(hour)==time.gmtime()[3]: 
			scheduledtweet=True
			debug('%s,%s' % (hour,str(time.gmtime()[3]) ))
			# We need to check to see if a tweet has already been sent for this scheduled hour
			if tempdata.has_key(hour):
				if tempdata[hour]==time.gmtime()[7]:
					debug('A scheduled or unscheduled tweet has already been sent this hour. Exiting')
					return 0
			if count==0: variables['scheduleindex']=0 # this is marking the first scheduled tweet of the day
			if count==len(variables['Schedule'])-1: variables['scheduleindex']=1 # this is marking the last scheduled tweet of the day
			if count !=0 and count!=len(variables['Schedule'])-1:variables['scheduleindex']=2 # this is marking the tweet as being neither the first or last
			debug( variables )
			break
		count=count+1

	if unscheduledtweet or scheduledtweet:
		# Calculate sunrise/sunset as this is included on the first & last tweet of the day
		astronomy=GetSunTimes.RiseAndSet(variables)
		variables['sunrises']=astronomy.sunrises
		variables['sunsets']=astronomy.sunsets
		variables['lastrecord']=DB.lastrecord
		variables['currentforecast']=DB.currentforecast
		variables['penultimateforecast']=DB.penultimateforecast
		tweet=TweetForecast.Tweet(variables)
		if unscheduledtweet: tweet.tweettype='unscheduled'
		if scheduledtweet: tweet.tweettype='scheduled'
		
		#print tweet.tweettype
		debug("Building tweet...")
		tweet.BuildTweet()
		updatetxt=tweet.tweettext
		twittervariables['update']=updatetxt
		twittervariables['lat']=float(variables['Latitude'])
		twittervariables['long']=float(variables['Longitude'])
		debug(variables)
		debug( "tweet=%s" % updatetxt )
		debug(twittervariables)		
		debug( twittervariables['update'] )

		try:
			tweet.SendTweet(twittervariables)
			tempdata[hour]=time.gmtime()[7]
		except:
			pass
	else:
		debug("No scheduled or unscheduled tweet due")

	debug(tempdata)
	pickle.dump( tempdata, open( tmpdatafile, "wb" ) )
	return 0

if __name__=='__main__':

	win32serviceutil.HandleCommandLine(AppServerSvc)

		
		
	
		
		
		
	
	

		
		
		
		
		
	
	




